﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.Serialization.Json;

namespace TheVerge.Base
{
    public static class API
    {

        public static void GetComments(long articleId, Action<Comments> OnResult, Action<Exception> OnError)
        {
            var url = string.Format(COMMENTS_ALL, articleId, API_KEY);
            MakeRequest(url, OnResult, OnError);
        }

        #region Forums Entries
        public static void GetForums(Action<Forums> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("forums");
            MakeRequest(url, OnResult, OnError);
        }

        public static void GetForumActive(int page, int forumId, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("entries", page) + @"forum_sort=active&html5_video=true&forum_ids=" + forumId;
            MakeRequest(url, OnResult, OnError);
        }
        public static void GetForumRecent(int page, int forumId, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("entries", page) + @"forum_sort=recent&html5_video=true&forum_ids=" + forumId;
            MakeRequest(url, OnResult, OnError);
        }
        public static void GetForumPopular(int page, int forumId, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("entries", page) + @"forum_sort=popular&html5_video=true&forum_ids=" + forumId;
            MakeRequest(url, OnResult, OnError);
        }
        #endregion

        #region Media
        public static void GetGalleries(int page, Action<APIResponse<GalleryEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("galleries", page);
            GetEntries(url, OnResult, OnError);
        }

        /// <summary>
        /// http://cdn0.sbnation.com/api/v2/entries/photos?api_key=rTvtu68O91ctXH9GHJVFlyxUtWjcsnuo&iphone_client_version=2&entry_id=3008671&width=640&height=216&format=png&compress=true
        /// </summary>
        public static string GetGalleryPhotoUrl(int EntryId, int Width, int Height)
        {
            return string.Format(CDN_BASE, API_KEY, EntryId, Width, Height);
        }

        public static string GetImage(Entry e, int width, int height)
        {
            return string.Format(CDN_BASE, API_KEY, e.Id, width, height);
        }

        public static void GetPodcasts(int page, Action<APIResponse<PodcastEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("podcasts", page);
            GetEntries(url, OnResult, OnError);
        }

        public static void GetVideos(int page, Action<APIResponse<VideoEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("videos", page);
            GetEntries(url, OnResult, OnError);
        }
        #endregion

        #region News
        public static void GetFeatured(int page, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("entries", page) + @"&main_content=true&entry_types=Feature&lax_filtering=true&html5_video=true";
            GetEntries(url, OnResult, OnError);
        }

        public static void GetLatest(int page, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("entries", page) + @"&main_content=true&html5_video=true";
            GetEntries(url, OnResult, OnError);
        }

        public static void GetReviews(int page, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl("entries", page) + @"&entry_types=ProductReview&main_content=true";
            GetEntries(url, OnResult, OnError);
        }
        #endregion

        #region Sections
        public static void GetBrands(Action<Brands> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl(@"brands");
            MakeRequest(url, OnResult, OnError);
        }

        public static void GetBrandEntries(int page, int brandId, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl(@"entries", page) + @"&html5_video=true&brand_ids[]=" + brandId;
            MakeRequest(url, OnResult, OnError);
        }


        public static void GetCategories(Action<Categories> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl(@"categories");
            MakeRequest(url, OnResult, OnError);
        }

        public static void GetCategoryEntries(int page, int categoryid, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl(@"entries", page) + @"&html5_video=true&category_ids[]=" + categoryid;
            MakeRequest(url, OnResult, OnError);
        }

        public static void GetHubs(Action<Hubs> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl(@"hubs");
            MakeRequest(url, OnResult, OnError);
        }

        public static void GetHubEntries(int page, int hubId, Action<APIResponse<ArticleEntry>> OnResult, Action<Exception> OnError)
        {
            var url = GetUrl(@"entries", page) + @"&html5_video=true&hub_ids[]=" + hubId;
            MakeRequest(url, OnResult, OnError);
        }
        #endregion

        private static void GetEntries<T>(string url, Action<APIResponse<T>> OnResult, Action<Exception> OnError)
        {
            MakeRequest(url, OnResult, OnError);
        }

        private static void MakeRequest<T>(string url, Action<T> OnResult, Action<Exception> OnError) where T : class
        {
            try
            {
                var request = HttpWebRequest.CreateHttp(url);

                request.BeginGetResponse(result =>
                {
                    try
                    {
                        var req = result.AsyncState as HttpWebRequest;
                        using (var response = req.EndGetResponse(result))
                        {
                            DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(T));
                            object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                            OnResult(objResponse as T);
                        }
                    }
                    catch (Exception inner)
                    {
                        OnError(inner);
                    }
                }, request);

            }
            catch (Exception exp) { OnError(exp); }
        }

        private const string API_KEY = @"rTvtu68O91ctXH9GHJVFlyxUtWjcsnuo";
        private const string BASE = @"http://www.theverge.com/api/v2/{0}?api_key={1}&iphone_client_version=2";
        private const string BASE_WITH_PAGE = BASE + @"&page={2}";
        private const string COMMENTS_ALL = @"http://www.theverge.com/api/v2/entries/{0}/comments?api_key={1}&iphone_client_version=2&offset=0";
        private const string CDN_BASE = @"http://cdn0.sbnation.com/api/v2/entries/photos?api_key={0}&iphone_client_version=2&entry_id={1}&width={2}&height={3}&format=png&compress=true";

        private static string GetUrl(string type) { return string.Format(BASE, type, API_KEY); }
        private static string GetUrl(string type, int page) { return string.Format(BASE_WITH_PAGE, type, API_KEY, page); }
    }
}
